/*
 * Copyright 2010 Thedwick, LLC

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

 */
package com.thedwick.jdbcGrabber.sink;

import java.io.File;
import java.io.IOException;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import com.thedwick.jdbcGrabber.util.IOUtil;
import com.thedwick.jdbcGrabber.util.ThreadUtil;

public class FileSummaryStore implements SummaryStore {
	private static final String VALUE_SEPARATOR = ",";
	private static final String KEY_SEPARATOR = " : ";
	private static final Object NEW_LINE = "\n";
	private static final Object STACK_END = "|";
	private final File targetSqlTableFile;
	private final File targetSqlCountsFile;
	private final File targetTraceTableFile;
	private final File targetTraceCountsFile;
	private final File targetTraceMappingFile;
	
	public FileSummaryStore(Properties config){
		String sinkName = config.getProperty("sink.name");
		String basePath = config.getProperty("fileSummaryStore.filePath");
		String sqlTableFileName = makePath(sinkName, basePath,"sqlTable");
		String traceTableFileName = makePath(sinkName, basePath,"traceTable");
		String sqlCountsFileName = makePath(sinkName, basePath,"sqlCounts");
		String traceCountsFileName = makePath(sinkName, basePath,"traceCounts");
		String traceMappingFileName = makePath(sinkName, basePath,"traceMapping");
		this.targetSqlTableFile = new File(sqlTableFileName);
		this.targetSqlCountsFile = new File(sqlCountsFileName);
		this.targetTraceTableFile = new File(traceTableFileName);
		this.targetTraceCountsFile = new File(traceCountsFileName);
		this.targetTraceMappingFile = new File(traceMappingFileName);
	}

	private String makePath(String sinkName, String basePath, String prefix) {
		return basePath + File.separator + prefix + "." + sinkName + ".dat";
	}
	
	@Override
	public void storeSQLTable(Map<Integer, NormalizedSQL> table) throws IOException {
		StringBuilder builder = new StringBuilder();
		for (Integer key : table.keySet()){
			builder.append(key);
			builder.append(KEY_SEPARATOR);
			builder.append(table.get(key).getSql());
			builder.append(NEW_LINE);
		}
		String outputString = builder.toString();
		IOUtil.safeAppend(outputString, this.targetSqlTableFile);
	}

	@Override
	public void updateSQLCounts(Map<Integer, Long> counts) throws IOException {
		StringBuilder builder = new StringBuilder();
		for (Integer key : counts.keySet()){
			builder.append(key);
			builder.append(KEY_SEPARATOR);
			builder.append(counts.get(key));
			builder.append(NEW_LINE);
		}
		IOUtil.safeReplace(builder.toString(), this.targetSqlCountsFile);
	}

	@Override
	public void storeTraceTable(Map<Integer, StackTraceElement[]> table) throws IOException {
		StringBuilder builder = new StringBuilder();
		for (Integer key : table.keySet()){
			builder.append(key);
			builder.append(KEY_SEPARATOR);
			builder.append(NEW_LINE);
			builder.append(ThreadUtil.formatStackTrace(table.get(key)));
			builder.append(STACK_END);
			builder.append(NEW_LINE);
		}		
		IOUtil.safeAppend(builder.toString(), this.targetTraceTableFile);
	}

	@Override
	public void updateTraceCounts(Map<Integer, Long> counts) throws IOException {
		StringBuilder builder = new StringBuilder();
		for (Integer key : counts.keySet()){
			builder.append(key);
			builder.append(KEY_SEPARATOR);
			builder.append(counts.get(key));
			builder.append(NEW_LINE);
		}
		IOUtil.safeReplace(builder.toString(), this.targetTraceCountsFile);
	}

	@Override
	public void storeTraceMapping(Map<Integer, Set<Integer>> sqlToTrace)
			throws IOException {
		StringBuilder builder = new StringBuilder();
		for (Integer sqlKey : sqlToTrace.keySet()){
			builder.append(sqlKey);
			builder.append(KEY_SEPARATOR);
			for (Integer traceKey : sqlToTrace.get(sqlKey)){
				builder.append(traceKey);
				builder.append(VALUE_SEPARATOR);
			}
			builder.append(NEW_LINE);
		}
		IOUtil.safeAppend(builder.toString(), this.targetTraceMappingFile);
	}

}
